package ioc.entry.resources;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;


import java.io.InputStream;
import java.util.List;

/**
 * @author songyouchao
 * @ClassName XmlBeanDefinitionReader.java
 * @Description 解析配置 将bean注册到容器中 也就是调用DefaultListableBeanFactory 的 registerBeanDefinition方法
 * @createTime 2021年07月27日
 */
public class XmlBeanDefinitionReader extends XmlBeanFactory {

    private DefaultListableBeanFactory beanFactory;

    public XmlBeanDefinitionReader (DefaultListableBeanFactory beanFactory){
        this.beanFactory = beanFactory;
    }

    /**
    *
     * @Author songyouchao
     * @Description  解析配置文件 所以传入一个配置文件的路径 解析之后将进行注册 registerBeanDefinition方法
     * @Date 20:02 2021/7/27
     * @Param [configPath]
     * @return void
     **/
    public void loadBeanDefinitions(String configPath){

        //1. 通过dom4j解析xml得到Document文档

        Document document = doLoadDocument(configPath);

        //2. 遍历文档所有Bean标签
        Element rootElement = document.getRootElement();
        List<Element> list = rootElement.selectNodes("//bean");


        //3. 解析每一个Bean标签 封装一个BeanDefinition对象
        //4. 解析每一个Bean标签下的所有Property标签 封装一个Property对象
        for(Element element : list){
            BeanDefinition beanDefinition = parseBeanDefinition(element);


            //5. 将BeanDefinition和Property对象注册到容器
            beanFactory.registerBeanDefinition(beanDefinition);
        }

        /**
         * 小结： 做到这里 其实就已经算是把实例的名称和实例所属的哪个类 注册到容器中了 接下来就是要真正的去创建这个单例的bean 多例的模式就不考虑了
         */
    }

    /**
    *
     * @Author songyouchao
     * @Description  这里将xml进行解析 返回出来一个BeanDefinition 这里面已经组织好这个实例属性
     * @Date 20:14 2021/7/27
     * @Param [element]
     * @return ioc.entry.resources.BeanDefinition
     **/
    BeanDefinition parseBeanDefinition(Element element){
        String beanName = element.attributeValue("id");
        String className = element.attributeValue("class");
        String scope = element.attributeValue("scope");
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setBeanName(beanName);
        beanDefinition.setClassName(className);
        if(scope!=null&&!"".equals(scope)){
            beanDefinition.setScope(scope);
        }
        List<Element> propertyList = element.selectNodes("property");
        //解析属性
        for(Element element1 : propertyList){
            Property property = new Property();
            property.setName(element1.attributeValue("name"));
            property.setValue(element1.attributeValue("value"));
            property.setRef(element1.attributeValue("ref"));
            beanDefinition.getPropertyList().add(property);
        }
        return beanDefinition;
    }

    /**
     * 解析Document文档
     * @param configPath
     * @return
     */
    Document doLoadDocument(String configPath){
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(configPath);
        SAXReader saxReader = new SAXReader();
        try {
            return saxReader.read(inputStream);
        } catch (DocumentException e) {
            e.printStackTrace();
            System.out.println("解析xml出现异常==>"+e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }
}
